home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / doc / sg3-utils / examples / sg_sat_set_features.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-05-01  |  9.8 KB  |  281 lines

  1. /*
  2.  * Copyright (c) 2006-2007 Douglas Gilbert.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. The name of the author may not be used to endorse or promote products
  14.  *    derived from this software without specific prior written permission.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26.  * SUCH DAMAGE.
  27.  *
  28.  */
  29.  
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <getopt.h>
  37. #include <sys/ioctl.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40.  
  41. #include "sg_lib.h"
  42. #include "sg_io_linux.h"
  43.  
  44. /* This program performs a ATA PASS-THROUGH (16) SCSI command in order
  45.    to perform an ATA SET FEATURES command. See http://www.t10.org
  46.    SAT draft at time of writing: sat-r09.pdf
  47.  
  48.    Invocation:
  49.         sg_sat_set_features [-c <n>] [-f <n>] [-h] [-l <n>] [-v] [-V] <device>
  50.  
  51. */
  52.  
  53. #define SAT_ATA_PASS_THROUGH16 0x85
  54. #define SAT_ATA_PASS_THROUGH16_LEN 16
  55. #define SAT_ATA_RETURN_DESC 9  /* ATA Return (sense) Descriptor */
  56.  
  57. #define ATA_SET_FEATURES 0xef
  58.  
  59. #define EBUFF_SZ 256
  60.  
  61. static char * version_str = "1.02 20070406";
  62.  
  63. static struct option long_options[] = {
  64.         {"count", required_argument, 0, 'c'},
  65.         {"chk_cond", no_argument, 0, 'C'},
  66.         {"feature", required_argument, 0, 'f'},
  67.         {"help", no_argument, 0, 'h'},
  68.         {"lba", required_argument, 0, 'l'},
  69.         {"verbose", no_argument, 0, 'v'},
  70.         {"version", no_argument, 0, 'V'},
  71.         {0, 0, 0, 0},
  72. };
  73.  
  74. void usage()
  75. {
  76.     fprintf(stderr, "Usage: "
  77.           "sg_sat_set_features [--count=C] [--chk_cond] [--feature=F] "
  78.           "[--help]\n"
  79.           "                           [-lba=LBA] [--verbose] [--version] "
  80.           "DEVICE\n"
  81.           "  where:\n"
  82.           "    --count=C|-c C       count field contents (def: 0)\n"
  83.           "    --chk_cond|-C        set chk_cond field in pass-through "
  84.           "(def: 0)\n"
  85.           "    --feature=F|-f F     feature field contents (def: 0)\n"
  86.           "    --help|-h            output this usage message\n"
  87.           "    --lba=LBA| -l LBA    LBA field contents (def: 0)\n"
  88.           "    --verbose|-v         increase verbosity\n"
  89.           "    --version|-V         print version string and exit\n\n"
  90.           "Sends an ATA SET FEATURES command via a SAT pass through.\n"
  91.           "Primary feature code is placed in '--feature=F' with '--count=C' "
  92.           "and\n"
  93.           "'--lba=LBA' being auxiliaries for some features.  The arguments C, "
  94.           "F and LBA\n"
  95.           "are decimal unless prefixed by '0x' or have a trailing 'h'.\n"
  96.           "Example enabling write cache: 'sg_sat_set_feature --feature=2 "
  97.           "/dev/sdc'\n");
  98. }
  99.  
  100. int main(int argc, char * argv[])
  101. {
  102.     int sg_fd, c, k;
  103.     unsigned char aptCmdBlk[SAT_ATA_PASS_THROUGH16_LEN] =
  104.                 {SAT_ATA_PASS_THROUGH16, 0, 0, 0, 0, 0, 0, 0,
  105.                  0, 0, 0, 0, 0, 0, 0, 0};
  106.     sg_io_hdr_t io_hdr;
  107.     char device_name[256];
  108.     char ebuff[EBUFF_SZ];
  109.     unsigned char sense_buffer[64];
  110.     int count = 0;
  111.     int feature = 0;
  112.     int lba = 0;
  113.     int verbose = 0;
  114.     int extend = 0;
  115.     int chk_cond = 0;   /* set to 1 to read register(s) back */
  116.     int protocol = 3;   /* non-dat data-in */
  117.     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
  118.     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
  119.     int t_length = 0;   /* 0 -> no data transferred, 2 -> sector count */
  120.     const unsigned char * ucp = NULL;
  121.  
  122.     memset(device_name, 0, sizeof(device_name));
  123.     while (1) {
  124.         int option_index = 0;
  125.  
  126.         c = getopt_long(argc, argv, "c:Cf:hl:vV", long_options,
  127.                         &option_index);
  128.         if (c == -1)
  129.             break;
  130.  
  131.         switch (c) {
  132.         case 'c':
  133.             count = sg_get_num(optarg);
  134.             if ((count < 0) || (count > 255)) {
  135.                 fprintf(stderr, "bad argument for '--count'\n");
  136.                 return SG_LIB_SYNTAX_ERROR;
  137.             }
  138.             break;
  139.         case 'C':
  140.             chk_cond = 1;
  141.             break;
  142.         case 'f':
  143.             feature = sg_get_num(optarg);
  144.             if ((feature < 0) || (feature > 255)) {
  145.                 fprintf(stderr, "bad argument for '--feature'\n");
  146.                 return SG_LIB_SYNTAX_ERROR;
  147.             }
  148.             break;
  149.         case 'h':
  150.         case '?':
  151.             usage();
  152.             return 0;
  153.         case 'l':
  154.             lba = sg_get_num(optarg);
  155.             if ((lba < 0) || (lba > 255)) {
  156.                 fprintf(stderr, "bad argument for '--lba'\n");
  157.                 return SG_LIB_SYNTAX_ERROR;
  158.             }
  159.             break;
  160.         case 'v':
  161.             ++verbose;
  162.             break;
  163.         case 'V':
  164.             fprintf(stderr, "version: %s\n", version_str);
  165.             return 0;
  166.         default:
  167.             fprintf(stderr, "unrecognised option code 0x%x ??\n", c);
  168.             usage();
  169.             return SG_LIB_SYNTAX_ERROR;
  170.         }
  171.     }
  172.     if (optind < argc) {
  173.         if ('\0' == device_name[0]) {
  174.             strncpy(device_name, argv[optind], sizeof(device_name) - 1);
  175.             device_name[sizeof(device_name) - 1] = '\0';
  176.             ++optind;
  177.         }
  178.         if (optind < argc) {
  179.             for (; optind < argc; ++optind)
  180.                 fprintf(stderr, "Unexpected extra argument: %s\n",
  181.                         argv[optind]);
  182.             usage();
  183.             return SG_LIB_SYNTAX_ERROR;
  184.         }
  185.     }
  186.  
  187.     if ('\0' == device_name[0]) {
  188.         fprintf(stderr, "missing device name!\n");
  189.         usage();
  190.         return 1;
  191.     }
  192.  
  193.     if ((sg_fd = open(device_name, O_RDWR)) < 0) {
  194.         snprintf(ebuff, EBUFF_SZ,
  195.                  "sg_sat_set_features: error opening file: %s", device_name);
  196.         perror(ebuff);
  197.         return 1;
  198.     }
  199.  
  200.     /* Prepare ATA PASS-THROUGH COMMAND (16) command */
  201.     aptCmdBlk[14] = ATA_SET_FEATURES;
  202.     aptCmdBlk[1] = (protocol << 1) | extend;
  203.     aptCmdBlk[2] = (chk_cond << 5) | (t_dir << 3) |
  204.                    (byte_block << 2) | t_length;
  205.     aptCmdBlk[4] = feature;
  206.     aptCmdBlk[6] = count;
  207.     aptCmdBlk[8] = lba & 0xff;
  208.     aptCmdBlk[10] = (lba >> 8) & 0xff;
  209.     aptCmdBlk[12] = (lba >> 16) & 0xff;
  210.     if (verbose) {
  211.         fprintf(stderr, "    ata pass through(16) cdb: ");
  212.         for (k = 0; k < SAT_ATA_PASS_THROUGH16_LEN; ++k)
  213.             fprintf(stderr, "%02x ", aptCmdBlk[k]);
  214.         fprintf(stderr, "\n");
  215.     }
  216.  
  217.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  218.     io_hdr.interface_id = 'S';
  219.     io_hdr.cmd_len = sizeof(aptCmdBlk);
  220.     /* io_hdr.iovec_count = 0; */  /* memset takes care of this */
  221.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  222.     io_hdr.dxfer_direction = SG_DXFER_NONE;
  223.     io_hdr.dxfer_len = 0;
  224.     io_hdr.dxferp = NULL;
  225.     io_hdr.cmdp = aptCmdBlk;
  226.     io_hdr.sbp = sense_buffer;
  227.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  228.     /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
  229.     /* io_hdr.pack_id = 0; */
  230.     /* io_hdr.usr_ptr = NULL; */
  231.  
  232.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  233.         perror("sg_sat_set_features: SG_IO ioctl error");
  234.         close(sg_fd);
  235.         return 1;
  236.     }
  237.  
  238.     /* error processing: N.B. expect check condition, no sense ... !! */
  239.     switch (sg_err_category3(&io_hdr)) {
  240.     case SG_LIB_CAT_CLEAN:
  241.         break;
  242.     case SG_LIB_CAT_RECOVERED:  /* sat-r09 uses this sk */
  243.     case SG_LIB_CAT_NO_SENSE:   /* earlier SAT drafts used this */
  244.         ucp = sg_scsi_sense_desc_find(sense_buffer, sizeof(sense_buffer),
  245.                                       SAT_ATA_RETURN_DESC);
  246.         if (NULL == ucp) {
  247.             if (verbose > 1)
  248.                 printf("ATA Return Descriptor expected in sense but not "
  249.                        "found\n");
  250.             sg_chk_n_print3("ATA_16 command error", &io_hdr, 1);
  251.         } else if (verbose)
  252.             sg_chk_n_print3("ATA Return Descriptor", &io_hdr, 1);
  253.         if (ucp && ucp[3]) {
  254.             if (ucp[3] & 0x4)
  255.                 printf("error in returned FIS: aborted command\n");
  256.             else
  257.                 printf("error=0x%x, status=0x%x\n", ucp[3], ucp[13]);
  258.         }
  259.         break;
  260.     default:
  261.         fprintf(stderr, "unexpected SCSI sense category\n");
  262.         ucp = sg_scsi_sense_desc_find(sense_buffer, sizeof(sense_buffer),
  263.                                       SAT_ATA_RETURN_DESC);
  264.         if (NULL == ucp)
  265.             sg_chk_n_print3("ATA_16 command error", &io_hdr, 1);
  266.         else if (verbose)
  267.             sg_chk_n_print3("ATA Return Descriptor, as expected",
  268.                              &io_hdr, 1);
  269.         if (ucp && ucp[3]) {
  270.             if (ucp[3] & 0x4)
  271.                 printf("error in returned FIS: aborted command\n");
  272.             else
  273.                 printf("error=0x%x, status=0x%x\n", ucp[3], ucp[13]);
  274.         }
  275.         break;
  276.     }
  277.  
  278.     close(sg_fd);
  279.     return 0;
  280. }
  281.